#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX_SIZE 100
#define NUM_THREADS 4 // 假设线程数量

typedef struct {
    int tid;
} ThreadParam_t;

double A[MAX_SIZE][MAX_SIZE]; // 假设 A 是全局变量
int n; // 假设 n 是全局变量
sem_t sem_main, sem_workerstart[NUM_THREADS], sem_workerend[NUM_THREADS]; // 信号量

void *threadFunc(void *param) {
    ThreadParam_t *p = (ThreadParam_t *)param;
    int tid = p->tid;

    for (int k = 0; k < n; k++) {
        sem_wait(&sem_workerstart[tid]); // 阻塞，等待主线程完成除法操作（操作自己专属的信号量）

        // 循环划分任务
        for (int i = k + 1 + tid; i < n; i += NUM_THREADS) {
            // 消去
            for (int j = k + 1; j < n; j++) {
                A[i][j] = A[i][j] - A[i][k] * A[k][j];
            }
            A[i][k] = 0.0;
        }

        sem_post(&sem_main); // 唤醒主线程
        sem_wait(&sem_workerend[tid]); // 阻塞，等待主线程唤醒进入下一轮
    }

    pthread_exit(NULL);
}

int main() {
    // 初始化信号量
    sem_init(&sem_main, 0, 0);
    for (int i = 0; i < NUM_THREADS; i++) {
        sem_init(&sem_workerstart[i], 0, 0);
        sem_init(&sem_workerend[i], 0, 0);
    }

    // 创建线程
    pthread_t handles[NUM_THREADS];
    ThreadParam_t param[NUM_THREADS];
    for (int tid = 0; tid < NUM_THREADS; tid++) {
        param[tid].tid = tid;
        pthread_create(&handles[tid], NULL, threadFunc, &param[tid]);
    }

    for (int k = 0; k < n; ++k) {
        // 主线程做除法操作
        for (int j = k + 1; j < n; j++) {
            A[k][j] = A[k][j] / A[k][k];
        }
        A[k][k] = 1.0;

        // 开始唤醒工作线程
        for (int tid = 0; tid < NUM_THREADS; ++tid) {
            sem_post(&sem_workerstart[tid]);
        }

        for (int tid = 0; tid < NUM_THREADS; ++tid) {
            sem_wait(&sem_main);
        }

        for (int tid = 0; tid < NUM_THREADS; ++tid) {
            sem_post(&sem_workerend[tid]);
        }
    }

    // 等待所有线程结束
    for (int tid = 0; tid < NUM_THREADS; tid++) {
        pthread_join(handles[tid], NULL);
    }

    // 销毁信号量
    sem_destroy(&sem_main);
    for (int i = 0; i < NUM_THREADS; i++) {
        sem_destroy(&sem_workerstart[i]);
        sem_destroy(&sem_workerend[i]);
    }

    return 0;
}
